﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Spider
{
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();
        }
        #region 注册快捷键
        public delegate void HotkeyEventHandler(int HotKeyID);
        private int Hotkey1;
        public class Hotkey : System.Windows.Forms.IMessageFilter
        {
            Hashtable keyIDs = new Hashtable();
            IntPtr hWnd;

            public event HotkeyEventHandler OnHotkey;

            public enum KeyFlags
            {
                MOD_ALT = 0x1,
                MOD_CONTROL = 0x2,
                MOD_SHIFT = 0x4,
                MOD_WIN = 0x8
            }
            [DllImport("user32.dll")]
            public static extern UInt32 RegisterHotKey(IntPtr hWnd, UInt32 id, UInt32 fsModifiers, UInt32 vk);

            [DllImport("user32.dll")]
            public static extern UInt32 UnregisterHotKey(IntPtr hWnd, UInt32 id);

            [DllImport("kernel32.dll")]
            public static extern UInt32 GlobalAddAtom(String lpString);

            [DllImport("kernel32.dll")]
            public static extern UInt32 GlobalDeleteAtom(UInt32 nAtom);

            public Hotkey(IntPtr hWnd)
            {
                this.hWnd = hWnd;
                Application.AddMessageFilter(this);
            }

            public int RegisterHotkey(Keys Key, KeyFlags keyflags)
            {
                UInt32 hotkeyid = GlobalAddAtom(System.Guid.NewGuid().ToString());
                RegisterHotKey((IntPtr)hWnd, hotkeyid, (UInt32)keyflags, (UInt32)Key);
                keyIDs.Add(hotkeyid, hotkeyid);
                return (int)hotkeyid;
            }

            public void UnregisterHotkeys()
            {
                Application.RemoveMessageFilter(this);
                foreach (UInt32 key in keyIDs.Values)
                {
                    UnregisterHotKey(hWnd, key);
                    GlobalDeleteAtom(key);
                }
            }

            public bool PreFilterMessage(ref System.Windows.Forms.Message m)
            {
                if (m.Msg == 0x312)
                {
                    if (OnHotkey != null)
                    {
                        foreach (UInt32 key in keyIDs.Values)
                        {
                            if ((UInt32)m.WParam == key)
                            {
                                OnHotkey((int)m.WParam);
                                return true;
                            }
                        }
                    }
                }
                return false;
            }
        }

        public void OnHotkey(int HotkeyID) //Ctrl+L隐藏窗体，再按显示窗体。 
        {
            if (HotkeyID == Hotkey1)
            {
                if (this.Visible == true)
                {
                    this.Visible = false;
                    this.notifyI.Visible = true;
                }
                else
                    if (this.Visible == false)
                    {
                        this.Show();
                        if (this.WindowState == FormWindowState.Minimized)
                            this.WindowState = FormWindowState.Normal;

                        this.ShowInTaskbar = true;
                        this.notifyI.Visible = false;
                    }

            }
            //else
            //{
            //    this.Visible = false;
            //}
        }
        #endregion
        private Spider m_spider;
        private delegate void Dlog(int fileoffset, string url, string title, bool color);  //用来显示日志记录的

        private void btnBegin_Click(object sender, EventArgs e)
        {
            if (btnBegin.Text.Equals("取消"))
            {
                this.pboxIng.Visible = false;
                m_spider.Stop();//停止所有线程
                m_spider.Quit = true;
                this.btnBegin.Text = "开始";
                return;
            }
            #region 保存设置
            SpiderAccount.AllowURLType = this.txtOutType.Text.Trim();
            SpiderAccount.StartListPage = int.Parse(this.txtStartPage.Text.Trim());
            SpiderAccount.EndListPage = int.Parse(this.txtEndPage.Text.Trim());
            SpiderAccount.TemplateUrl = this.txtTemplateUrl.Text.Trim();
            SpiderAccount.ListUrlReg = this.txtUrlReg.Text.Trim();
            SpiderAccount.ContentUrlReg = this.txtContentReg.Text.Trim();
            SpiderAccount.StartStr = this.txtStartStr.Text.Trim();
            SpiderAccount.EndStr = this.txtEndStr.Text.Trim();
            SpiderAccount.DownloadPath = this.txtPath.Text.Trim();
            SpiderAccount.ThreadCount = int.Parse(this.txtThreadCount.Text.Trim());
            CreateDownloadDirectory(SpiderAccount.DownloadPath);

            AppConfiguration.SetConfiguration("url", SpiderAccount.Url);
            AppConfiguration.SetConfiguration("threadcount", this.txtThreadCount.Text.Trim());
            AppConfiguration.SetConfiguration("encoding", this.cmboxCode.SelectedValue.ToString());
            AppConfiguration.SetConfiguration("outtype", this.txtOutType.Text.Trim());
            AppConfiguration.SetConfiguration("startstr", this.txtStartStr.Text.Trim());
            AppConfiguration.SetConfiguration("endstr", this.txtEndStr.Text.Trim());
            AppConfiguration.SetConfiguration("urlcontain", this.txtUrlContain.Text.Trim());
            AppConfiguration.SetConfiguration("templateurl", this.txtTemplateUrl.Text.Trim());
            AppConfiguration.SetConfiguration("urlreg", this.txtUrlReg.Text.Trim());
            #endregion
            this.pboxIng.Visible = true;
            ThreadStart starter = new ThreadStart(this.SpiderThread);  //启动线程
            Thread spider = new Thread(starter);
            spider.Start();
            new HttpHelper().Encoding = Encoding.GetEncoding(this.cmboxCode.SelectedValue.ToString());
        }
        public void SpiderThread()
        {
            ChangeButton("取消");
            //CheckForIllegalCrossThreadCalls = false;
            m_spider = new Spider();
            m_spider.ReportTo = this; // 别的类更新UI，要用到FrmMain对象

            int threads = SpiderAccount.ThreadCount;      //线程数目
            try
            {
                m_spider.Start(new Uri(SpiderAccount.Url), threads);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            ChangeButton("开始");
            //btnBegin.Enabled = true;
        }
        #region Invoke封送改变按钮上的文字
        private delegate void ChangeButtonDelegate(string str);
        private void ChangeButton(string str)
        {
            // label.Text = number.ToString();
            // Do NOT do this, as we are on a different thread.

            // Check if we need to call BeginInvoke.
            if (this.InvokeRequired)
            {
                // Pass the same function to BeginInvoke,
                // but the call would come on the correct
                // thread and InvokeRequired will be false.
                this.BeginInvoke(new ChangeButtonDelegate(ChangeButton), new object[] { str });
                return;
            }
            this.btnBegin.Text = str;
        }
        #endregion

        public void CreateDownloadDirectory(string path)  //创建下载目录
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
        }
        private void SpiderForm_Load(object sender, EventArgs e)
        {
            btnReadCookie_Click(null, null);
        }

        private void btnBrowser_Click(object sender, EventArgs e)
        {
            folderbgPath.ShowDialog();
            if (string.IsNullOrEmpty(folderbgPath.SelectedPath))
            {
                this.txtPath.Text = "D:\\" + SpiderAccount.UrlHost + "\\" + DateTime.Now.ToString("yyyy-MM-dd");
            }
            else
            {
                this.txtPath.Text = folderbgPath.SelectedPath;
            }
        }

        private void btnReadCookie_Click(object sender, EventArgs e)
        {
            this.txtCookie.Text = CookieMng.GetCurrentCookie;
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            Hotkey hotkey;
            hotkey = new Hotkey(this.Handle);
            Hotkey1 = hotkey.RegisterHotkey(System.Windows.Forms.Keys.L, Hotkey.KeyFlags.MOD_CONTROL); //定义快键(Ctrl + L) 
            hotkey.OnHotkey += new HotkeyEventHandler(OnHotkey);

            this.txtPath.Text = "D:\\" + SpiderAccount.UrlHost + "\\" + DateTime.Now.ToString("yyyy-MM-dd");

            #region 没用了
            //string temp = SpiderAccount.Url;
            //if (temp.Contains("page="))
            //{
            //    string str = string.Empty;
            //    int i = temp.LastIndexOf("page=");
            //    int j = temp.IndexOf('&', i);
            //    if (j > i)
            //    {
            //        str = temp.Substring(i, j - i);
            //    }
            //    else
            //    {
            //        str = temp.Substring(i);
            //    }
            //    temp = temp.Replace(str, "page=[1]");
            //}
            //this.txtTemplateUrl.Text = temp;
            #endregion

            Log.InitLog();//初始化日志记录
            this.cmboxCode.DataSource = CompData.GetRequestEnCode();
            this.cmboxCode.DisplayMember = "text";
            this.cmboxCode.ValueMember = "value";

            #region  增加两列
            dgvLog.Columns.Add("Id", "编号");
            dgvLog.Columns[0].Width = 10;
            dgvLog.Columns.Add("Url", "Url");
            dgvLog.Columns.Add("Title", "标题");
            dgvLog.Rows.Insert(0, new object[] { "", "", "" });

            this.dgvLog.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            this.dgvLog.Columns[0].Width = 40;
            #endregion

            #region 初始化配置
            if (SpiderAccount.TemplateId != null)
            {
                LoadTemplate();
            }
            else
            {
                this.txtThreadCount.Text = AppConfiguration.GetConfiguration("threadcount");
                this.cmboxCode.SelectedValue = AppConfiguration.GetConfiguration("encoding");
                if (this.cmboxCode.SelectedValue == null)
                {
                    this.cmboxCode.SelectedIndex = 0;
                }
                this.txtOutType.Text = AppConfiguration.GetConfiguration("allowtype");
                this.txtStartStr.Text = AppConfiguration.GetConfiguration("startstr");
                this.txtEndStr.Text = AppConfiguration.GetConfiguration("endstr");
                this.txtOutType.Text = AppConfiguration.GetConfiguration("urlcontain");
                this.txtTemplateUrl.Text = AppConfiguration.GetConfiguration("templateurl");
                this.txtUrlReg.Text = AppConfiguration.GetConfiguration("listurl");
            }
            #endregion
        }

        private void 进入日志目录ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string directory = SpiderAccount.CurrentPath;
            directory = directory.Substring(0, directory.LastIndexOf('\\'));
            System.Diagnostics.Process.Start(directory);
        }

        private void 快捷键ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("登录后，程序到系统托盘快捷键Ctrl+L，若需帮助请看采集说明！\r\n 淘鞋技术部 v 1.0", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("你确定要退出应用程序吗？", "提示信息？",
                               MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK)
            {
                Application.ExitThread();//退出整个消息循环
            }
        }
        #region   显示处理Url的历史
        public void ShowLog(int fileoffset, string url, string title, bool color)
        {
            try
            {
                Dlog dlog = new Dlog(DelegateShowLog);
                this.BeginInvoke(dlog, new object[] { fileoffset, url, title, color });
            }
            catch (Exception err)
            {
                //MessageBox.Show(err.Message);
                //Application.Exit();
                System.Environment.Exit(0);
            }
        }
        /// <summary>
        /// 利用delegate显示日志记录
        /// </summary>
        /// <param name="url"></param>
        private void DelegateShowLog(int fileoffset, string url, string title, bool color)
        {
            //int k = 0;

            //string id = dgvLog.Rows[0].Cells[0].Value.ToString();
            //if (string.IsNullOrEmpty(id))
            //{
            //    id = "0";
            //}
            //k = int.Parse(id);

            dgvLog.Rows.Insert(0, new object[] { fileoffset, url, title });
            if (color)
            {
                this.dgvLog.Rows[0].DefaultCellStyle.BackColor = System.Drawing.Color.Red;
            }

            this.lblCount.Text = m_spider.m_urlCount + "/" + m_spider.m_urlFailCount;
            long elapse = DateTime.Now.Ticks - m_spider.m_startTime;
            TimeSpan ts = new TimeSpan(elapse);
            this.lblTime.Text = ts.TotalMinutes.ToString("f2") + " Minutes";
        }
        #endregion

        private void dgvLog_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dgvLog.Columns[e.ColumnIndex].HeaderText == "标题")
            {
                string title = dgvLog.CurrentCell.Value.ToString();
                title = Utility.ReplaceBadCharOfFileName(title);   //过滤title标签里的非法字符

                string fileoffset = this.dgvLog.CurrentRow.Cells[0].Value.ToString();
                if (fileoffset == "0")
                {
                    MessageBox.Show("这个可能是列表页或是无效的链接！");
                    return;
                }
                try
                {
                    string filename = SpiderAccount.DownloadPath + "\\" + fileoffset + title + ".txt";
                    System.Diagnostics.Process.Start(filename);
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message);
                }
            }
            else if (dgvLog.Columns[e.ColumnIndex].HeaderText == "Url")
            {
                string url = dgvLog.CurrentCell.Value.ToString();
                System.Diagnostics.Process.Start("IExplore.exe", url);
            }
        }
        public void DownloadComplete()
        {
            this.pboxIng.Visible = false;
        }
        #region 托盘图标
        private void FrmMain_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                this.ShowInTaskbar = false;
                this.notifyI.Visible = true;
            }
        }
        private void notifyI_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //鼠标左击
            {
                this.Show();
                if (this.WindowState == FormWindowState.Minimized)
                    this.WindowState = FormWindowState.Normal;

                this.ShowInTaskbar = true;
            }
        }
        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.Visible = false;
            this.notifyI.Visible = true;
        }
        private void toolSMIClose_Click(object sender, EventArgs e)
        {
            Application.ExitThread();//退出整个消息循环
            //Application.ExitThread(); //退出整个消息循环
        }

        private void toolSMIOpen_Click(object sender, EventArgs e)
        {
            this.Show();
            this.ShowInTaskbar = true;
        }
        #endregion

        private void 模板ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmTemplate frmTemplate = new FrmTemplate();
            frmTemplate.refreshFather += new EventHandler(frmTemplate_refreshFather);
            frmTemplate.ShowDialog();
        }
        /// <summary>
        /// 刷新父窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void frmTemplate_refreshFather(object sender, EventArgs e)
        {
            if (SpiderAccount.TemplateId != null)
            {
                LoadTemplate();
            }
        }

        private void LoadTemplate()
        {
            Hashtable ht = new CompData().GetTemplateData(SpiderAccount.TemplateId);
            foreach (Control c in this.Controls)
            {
                if (c.GetType().Name.Equals("TextBox"))
                {
                    foreach (string name in ht.Keys)
                    {
                        if (c.Name.ToLower() == "txt" + name)
                        {
                            c.Text = ht[name].ToString();
                        }
                    }
                }
            }
            SpiderAccount.Url = ht["url"].ToString();
            this.txtPath.Text = "D:\\" + SpiderAccount.UrlHost + "\\" + DateTime.Now.ToString("yyyy-MM-dd");
            this.cmboxCode.SelectedValue = ht["encoding"].ToString();
        }
        private void 升级ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmUpdate frmUpdate = new FrmUpdate();
            frmUpdate.ShowDialog();
        }

        private void 进入下载ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string directory = SpiderAccount.DownloadPath;
                System.Diagnostics.Process.Start(directory);
            }
            catch
            {
                MessageBox.Show("程序需要开始后，才能创建下载目录！");
            }
        }
    }
}
